Global Accelerator + ALB で www 付きドメインへのリダイレクトを CloudFormation 一撃してみた

Global Accelerator + ALB で www 付きドメインへのリダイレクトを CloudFormation 一撃してみた

Clock Icon2024.12.18

AWS事業本部の梶原@福岡オフィスです。

外部DNSサービスを使用している場合、Zone Apex ドメイン(例:example.com)から www 付きドメイン(例:www.example.com)へのリダイレクトを実現するには、DNSへA レコードの登録が必要で、固定IPアドレスが必要になります。今回は、AWS Global AcceleratorとALBを組み合わせたソリューションをCloudFormationで一発構築する方法をご紹介します。

なお、ドメインをRoute53 で管理している場合、ALIAS レコードを使用することにより固定IPを使用せずに、Zone Apex に対して設定することができますので、以下のような構成で対応することができます。

Zone Apex のドメインをリダイレクトする場合のコストや運用の手間などを鑑みた私のお勧め順です。
実装方法はたくさん紹介されているので割愛します

Route53 で管理して(ALIAS レコードを使って)

  • S3 Website Hosting でリダイレクト(HTTPのみ)
  • CloudFront + S3 Website Hosting でリダイレクト(HTTPSも)
  • CloudFront + Lamada@Edge でリダイレクト
  • CloudFront + CloudFunctions でリダイレクト
  • API-Gateway + Lambda でリダイレクト

外部のDNS で管理して(A レコードを使って)

  • Global Accelerator + ALB でリダイレクト (本ブログ)
  • EC2 にEIPつけて、Apache/nginx などで頑張る

他にもあるかと思いますが今回は、Global Accelerator + ALB でリダイレクト をやる機会があるかもよ。ということでブログ書いてみました。

詳細は後述しますが、お急ぎの方は、末尾にあるCloudFormation Template からスタックを作成してください

ユースケース

  • Route53ではなく外部DNSサービスを使用していて、ALIASレコードが使用できません
  • グローバルに展開するWebサイトで低レイテンシーなリダイレクトが必要です
  • リクエスト数が予測できないのでスケールする必要があります
  • HTTPのみで良い(HTTPSをサポートする必要がある場合の追加部分は説明補足しています)
  • なるはやで

各リソースの説明

ALBリスナーの設定

今回のリダイレクトのメイン処理です。HTTPのみのリスナーのリダイレクトルールを設定しています。

HTTPListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  Properties:
    Protocol: HTTP
    Port: 80
    DefaultActions:
      - Type: redirect
        RedirectConfig:
          Protocol: HTTPS
          Port: '443'
          Host: 'www.#{host}'
          Path: '/#{path}'
          Query: '#{query}'
          StatusCode: HTTP_301
  • ホストヘッダーを利用した動的リダイレクトを設定します
  • HTTPSへの自動リダイレクトを行います

Global Acceleratorの設定

GlobalAccelerator:
  Type: AWS::GlobalAccelerator::Accelerator
  Properties:
    Name: domain-redirect-accelerator
    IpAddressType: IPV4
    Enabled: true
  • 固定IPv4アドレスを提供します

出力設定

Outputs:
  GlobalAcceleratorIPs:
    Value: !Join
      - ', '
      - !GetAtt GlobalAccelerator.Ipv4Addresses
  • DNSで設定する固定IPアドレスを出力します

完全なテンプレートはブログ最後で公開しています。

注意点

  1. 個別ドメイン設定の推奨
    • 提示したテンプレートは全てのドメインをwww付きにリダイレクトします
    • 本番環境では以下のような特定のドメインに対してリスナールールの使用を推奨します:
ListenerRule:
  Type: AWS::ElasticLoadBalancingV2::ListenerRule
  Properties:
    Priority: 1
    Conditions:
      - Field: host-header
        Values: 
          - example.com
    Actions:
      - Type: redirect
        RedirectConfig:
          Protocol: HTTPS
          Port: '443'
          Host: 'www.example.com'
          Path: '/#{path}'
          Query: '#{query}'
          StatusCode: HTTP_301
  1. HTTPSの実装
    • 本番環境ではACM証明書を使用したHTTPSの実装を推奨します
    • 証明書の取得と検証が必要です
Certificate:
  Type: AWS::CertificateManager::Certificate
  Properties:
    DomainName: example.com
    SubjectAlternativeNames:
      - www.example.com
    ValidationMethod: DNS
  1. DNSの設定

Outputに出力されたGlobal Accelerator のIPv4 アドレスをDNSに登録してください

example.com.    A    <Global Accelerator IP 1>
example.com.    A    <Global Accelerator IP 2>

まとめ

CloudFormationを使用することで、Global AcceleratorとALBを組み合わせたwwwリダイレクト環境を簡単に構築できます。
Route53以外のDNSサービスを使用している場合の実装の参考になれば幸いです

参考

https://aws.amazon.com/jp/blogs/networking-and-content-delivery/solving-dns-zone-apex-challenges-with-third-party-dns-providers-using-aws/

テンプレート

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Apex Domain to www redirect using ALB with optional Global Accelerator'

Parameters:
  UseGlobalAccelerator:
    Type: String
    Description: 'Whether to use Global Accelerator'
    AllowedValues: 
      - 'true'
      - 'false'
    Default: 'false'

Conditions:
  CreateGlobalAccelerator: !Equals [!Ref UseGlobalAccelerator, 'true']

Resources:
  # VPC for ALB
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: RedirectVPC

  # Public Subnets
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: RedirectPublicSubnet1

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [1, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: RedirectPublicSubnet2

  # Internet Gateway
  InternetGateway:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # Route Table
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable

  # Application Load Balancer
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for ALB
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      Type: application

  # ALB Listener
  HTTPListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Protocol: HTTPS
            Port: '443'
            Host: 'www.#{host}'
            Path: '/#{path}'
            Query: '#{query}'
            StatusCode: HTTP_301

  # Global Accelerator (Conditional)
  GlobalAccelerator:
    Type: AWS::GlobalAccelerator::Accelerator
    Condition: CreateGlobalAccelerator
    Properties:
      Name: domain-redirect-accelerator
      IpAddressType: IPV4
      Enabled: true

  Listener:
    Type: AWS::GlobalAccelerator::Listener
    Condition: CreateGlobalAccelerator
    Properties:
      AcceleratorArn: !Ref GlobalAccelerator
      PortRanges:
        - FromPort: 80
          ToPort: 80
      Protocol: TCP

  EndpointGroup:
    Type: AWS::GlobalAccelerator::EndpointGroup
    Condition: CreateGlobalAccelerator
    Properties:
      ListenerArn: !Ref Listener
      EndpointGroupRegion: !Ref 'AWS::Region'
      EndpointConfigurations:
        - EndpointId: !Ref ApplicationLoadBalancer
          Weight: 100
          ClientIPPreservationEnabled: true

Outputs:
  EndpointToUse:
    Description: Endpoint to use for DNS configuration
    Value: !If 
      - CreateGlobalAccelerator
      - !GetAtt GlobalAccelerator.DnsName
      - !GetAtt ApplicationLoadBalancer.DNSName

  GlobalAcceleratorIPs:
    Condition: CreateGlobalAccelerator
    Description: Static IP addresses for Global Accelerator (use these for Apex domain A records)
    Value: !Join 
      - ', '
      - !GetAtt GlobalAccelerator.Ipv4Addresses

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.